﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using SingleUserMall.Authorization.Users;
using SingleUserMall.Common;
using SingleUserMall.Coupons;
using SingleUserMall.Items;
using SingleUserMall.Items.VO;
using SingleUserMall.Orders.Form;
using SingleUserMall.Orders.VO;
using SingleUserMall.Workers;
//using SingleUserMall.Workers.VO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SingleUserMall.Users;
using SingleUserMall.Stores;
using Abp.Domain.Uow;
using System.Data.Entity;
using Abp.Collections.Extensions;
using SingleUserMall.ShoppingCarts;
using SingleUserMall.Logistics;

namespace SingleUserMall.Orders
{
    [AbpAuthorize]
    public class OrderAppService : SingleUserMallAppServiceBase, IOrderAppService
    {
        private readonly IRepository<Order, long> _orderRepository;
        private readonly IRepository<OrderDetail, long> _orderDetailRepository;
        private readonly IRepository<UserAddress, long> _userAddressRepository;
        private readonly IRepository<Coupon, long> _couponRepository;
        private readonly IRepository<UserCoupon, long> _userCouponRepository;
        private readonly IRepository<Item, long> _itemRepository;
        private readonly IRepository<ItemSpec, long> _itemSpecRepository;
        private readonly IRepository<ItemComment, long> _itemCommentRepository;
        private readonly IRepository<GroupOrder, long> _groupOrderRepository;
        private readonly IRepository<GroupOrderDetail, long> _groupOrderDetailRepository;
        private readonly IRepository<Worker, long> _workerDetailRepository;
        private readonly IRepository<Store, int> _storeRepository;
        private readonly IRepository<User, long> _userRepository;
        private readonly IRepository<LogisticsEntity, long> _logisticsEntityRepository;
        public OrderManager OrderManager { get; set; }
        public OrderAppService(
            IRepository<Order, long> orderRepository,
            IRepository<OrderDetail, long> orderDetailRepository,
            IRepository<UserAddress, long> userAddressRepository,
            IRepository<Coupon, long> couponRepository,
            IRepository<UserCoupon, long> userCouponRepository,
            IRepository<Item, long> itemRepository,
            IRepository<ItemSpec, long> itemSpecRepository,
            IRepository<ItemComment, long> itemCommentRepository,
            IRepository<GroupOrder, long> groupOrderRepository,
            IRepository<GroupOrderDetail, long> groupOrderDetailRepository,
            IRepository<Worker, long> workerDetailRepository,
            IRepository<Store, int> storeRepository,
            IRepository<User, long> userRepository,
            IRepository<LogisticsEntity, long> logisticsEntityRepository
            )
        {
            _orderRepository = orderRepository;
            _orderDetailRepository = orderDetailRepository;
            _userAddressRepository = userAddressRepository;
            _couponRepository = couponRepository;
            _userCouponRepository = userCouponRepository;
            _itemRepository = itemRepository;
            _itemSpecRepository = itemSpecRepository;
            _itemCommentRepository = itemCommentRepository;
            _groupOrderRepository = groupOrderRepository;
            _groupOrderDetailRepository = groupOrderDetailRepository;
            _workerDetailRepository = workerDetailRepository;
            _storeRepository = storeRepository;
            _userRepository = userRepository;
            _logisticsEntityRepository = logisticsEntityRepository;
        }
        public async Task<PagedResultDto<OrderMiniVO>> GetOrdersAsync(OrderPagedForm form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                var userId = AbpSession.GetUserId();
                var user = await UserManager.FindByIdAsync(userId);
                var query = _orderRepository.GetAll().Where(x => x.OrderType == OrderType.Shopping && x.Status > OrderStatus.Init && x.Status != OrderStatus.Cancel && x.ShoppingCartType == ShoppingCarts.ShoppingCartType.ShoppingItems)
                    .Where(x => x.UserId == userId)
                    .WhereIf(form.Status == OrderWaitStatus.WaitPay, x => x.Status == OrderStatus.WaitPay)
                    .WhereIf(form.Status == OrderWaitStatus.WaitGroup, x => x.Status == OrderStatus.Paid && x.IsGroup)
                    .WhereIf(form.Status == OrderWaitStatus.WaitSend, x => (x.Status == OrderStatus.Paid && !x.IsGroup) || (x.Status == OrderStatus.Group && x.IsGroup))
                    .WhereIf(form.Status == OrderWaitStatus.WaitGet, x => x.Status == OrderStatus.Sent && x.ShippingType != ShippingType.Get)
                    .WhereIf(form.Status == OrderWaitStatus.WaitLift, x => x.Status <= OrderStatus.Sent && x.Status > OrderStatus.Paid && x.ShippingType == ShippingType.Get)
                    .WhereIf(form.Status == OrderWaitStatus.WaitAppraise, x => x.Status == OrderStatus.Successed)
                    .WhereIf(form.Status == OrderWaitStatus.Invalidation, x => x.Status == OrderStatus.Invalidation)
                    .OrderByDescending(x => x.CreationTime);
                return await query.ToPagedResultDtoAsync<Order, OrderMiniVO>(form, (o, vo) =>
                {
                    if (o.MinTreeNumber != null)
                    {
                        vo.TreeNumberRange = (o.MinTreeNumber == o.MaxTreeNumber) ? o.MinTreeNumber : o.MinTreeNumber + "~" + o.MaxTreeNumber;
                    }
                    if(o.MinTreeNumber != null)
                    {
                        vo.TreeNumberRange = (o.MinTreeNumber == o.MaxTreeNumber) ? o.MinTreeNumber : o.MinTreeNumber + "~" + o.MaxTreeNumber;
                    }
                    vo.OrderDetails = o.OrderDetails.Where(x => x.IsRefund == false).ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                     {
                         var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                         var store = _storeRepository.FirstOrDefault(itemSpec.Item.StoreId);
                         dvo.inItem = itemSpec.Item;
                         dvo.inItemSpec = itemSpec;
                         dvo.CustomerServicePhone = store.CustomerServicePhone;
                     });
                });
            }
        }
        public async Task<PagedResultDto<OrderDividendMiniVO>> GetTreeOrdersAsync(OrderPagedForm form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                var userId = AbpSession.GetUserId();
                var user = await UserManager.FindByIdAsync(userId);
                IQueryable<Order> query = _orderRepository.GetAll().Where(x => x.OrderType == OrderType.Shopping && x.Status != OrderStatus.Init && x.ShoppingCartType == ShoppingCarts.ShoppingCartType.TreeShopping && x.DividendItemStatus == form.DividendItemStatus)
                    .WhereIf(form.FriendType.HasValue && form.FriendType == OrderFriendType.Own, x => x.UserId == userId && x.FriendUserId == null)
                    .WhereIf(form.FriendType.HasValue && form.FriendType == OrderFriendType.FriendToMySelf, x => x.FriendUserId == userId)
                    .WhereIf(form.FriendType.HasValue && form.FriendType == OrderFriendType.OwnToFriend, x => x.UserId == userId && x.FriendUserId != null)
                    .WhereIf(!form.FriendType.HasValue, x => x.UserId == userId && x.FriendUserId == null)
                    .WhereIf(form.Status == OrderWaitStatus.WaitPay, x => x.Status == OrderStatus.WaitPay)
                    .WhereIf(form.Status == OrderWaitStatus.WaitGroup, x => x.Status == OrderStatus.Paid && x.IsGroup)
                    .WhereIf(form.Status == OrderWaitStatus.WaitSend, x => (x.Status == OrderStatus.Paid && !x.IsGroup) || (x.Status == OrderStatus.Group && x.IsGroup))
                    .WhereIf(form.Status == OrderWaitStatus.WaitGet, x => x.Status == OrderStatus.Sent && x.ShippingType != ShippingType.Get)
                    .WhereIf(form.Status == OrderWaitStatus.WaitLift, x => x.Status <= OrderStatus.Sent && x.Status > OrderStatus.Paid && x.ShippingType == ShippingType.Get)
                    .WhereIf(form.Status == OrderWaitStatus.WaitAppraise, x => x.Status == OrderStatus.Successed)
                    .WhereIf(form.Status == OrderWaitStatus.Invalidation, x => x.Status == OrderStatus.Invalidation)
                    .OrderByDescending(x => x.CreationTime);
                return await query.ToPagedResultDtoAsync<Order, OrderDividendMiniVO>(form, (o, vo) =>
                {
                    vo.Avatar = o.User.Avatar;
                    vo.UserName = o.User.Name;
                    vo.PhoneNumber = o.User.PhoneNumber;
                    if (o.IsFriend)
                    {
                        var friend = _userRepository.FirstOrDefault(x => x.Id == o.FriendUserId);
                        vo.FriendAvatar = friend.Avatar;
                        vo.FriendUserName = friend.Name;
                    }
                    vo.OrderDetails = o.OrderDetails.ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                    {
                        var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                        var store = _storeRepository.FirstOrDefault(itemSpec.Item.StoreId);
                        var orders = _orderRepository.FirstOrDefault(x => x.OrderDetails.FirstOrDefault().Id == d.Id);
                        dvo.inItem = itemSpec.Item;
                        dvo.inItemSpec = itemSpec;
                        dvo.CustomerServicePhone = store.CustomerServicePhone;
                        dvo.DividendAmountView = ((int)(dvo.DividendAmount * 100)).ToString();
                        if(dvo.Timelimit > 0)
                        {
                            dvo.DividendAmountViewByYear = ((int)(dvo.DividendAmount * 100 / dvo.Timelimit * 12)).ToString();
                        }
                    });
                });
            }
        }
        public async Task<OrderVO> GetOrderAsync(SingleId<long> form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
                var userId = AbpSession.GetUserId();
                var user = await UserManager.FindByIdAsync(userId);
                return order.ToVO<Order, OrderVO>((o, vo) =>
                {
                    if (order.ShoppingCartType == ShoppingCartType.ShoppingItems)
                    {
                        vo.EndDateTime = o.CreationTime.AddDays(+1);
                    }
                    else
                    {
                        var timeLimits = o.OrderDetails.Select(x => x.ItemSpec?.Item?.Timelimit).OrderBy(x => x).FirstOrDefault() ?? 0;
                        vo.EndDateTime = o.PayTime.HasValue ? o.PayTime.Value.AddDays(timeLimits) : o.PayTime;
                    }
                    if (order != null)
                    {
                        if (o.MinTreeNumber != null)
                        {
                            vo.TreeNumberRange = (o.MinTreeNumber == o.MaxTreeNumber) ? o.MinTreeNumber : o.MinTreeNumber + "~" + o.MaxTreeNumber;
                        }
                        vo.Avatar = order.User.Avatar;
                        vo.UserName = order.User.Name;
                        if(order.IsFriend)
                        {
                            var friend = _userRepository.FirstOrDefault(x => x.Id == order.FriendUserId);
                            vo.FriendAvatar = friend.Avatar;
                            vo.FriendUserName = friend.Name;
                        }
                    }
                    vo.OrderDetails = o.OrderDetails.ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                     {
                         var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                         var store = _storeRepository.FirstOrDefault(itemSpec.Item.StoreId);
                         dvo.inItem = itemSpec.Item;
                         dvo.inItemSpec = itemSpec;
                         dvo.CustomerServicePhone = store.CustomerServicePhone;
                         dvo.DividendAmountView = ((int)(dvo.DividendAmount * 100)).ToString();
                         if(dvo.Timelimit > 0)
                         {
                             dvo.DividendAmountViewByYear = ((int)(dvo.DividendAmount * 100 / dvo.Timelimit * 12)).ToString();
                         }
                     });
                });
            }
        }

        public async Task<OrderVO> GetOrderLogisticsAsync(SingleId<long> form)
        {
            using (CurrentUnitOfWork.DisableFilter(AbpDataFilters.SoftDelete))
            {
                var lastQueryTime = DateTime.Now.AddHours(-4);
                var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
                var logistics = _logisticsEntityRepository.FirstOrDefault(1);
                if (!string.IsNullOrWhiteSpace(order.ShippingNo) && logistics.Qty > 0 && order.Status == OrderStatus.Sent && order.LastShippingLogTime == null || order.LastShippingLogTime < lastQueryTime)
                {
                    var response = ExpressContext.Instance.Query(order.ShippingNo);
                    order.ShippingLog = response;
                    order.LastShippingLogTime = DateTime.Now;
                    logistics.Qty -= 1;
                    CurrentUnitOfWork.SaveChanges();
                }
                return order.ToVO<Order, OrderVO>((o, vo) =>
                {
                });
            }
        }

        public async Task<ListResultDto<UserAddressVO>> GetUserAddressesAsync()
        {
            var userId = AbpSession.GetUserId();
            var query = _userAddressRepository.GetAll().Where(x => x.UserId == userId && x.IsFriendAddress == false)
                .OrderByDescending(x => x.IsDefault);
            return await query.ToListResultDtoAsync<UserAddress, UserAddressVO>();
        }

        public async Task<ListResultDto<UserAddressVO>> GetUserFriendAddressesAsync()
        {
            var userId = AbpSession.GetUserId();
            var query = _userAddressRepository.GetAll().Where(x => x.UserId == userId && x.IsFriendAddress == true)
               .OrderByDescending(x => x.IsDefault);
            return await query.ToListResultDtoAsync<UserAddress, UserAddressVO>();

        }

        public async Task<OrderVO> PayAsync(OrderPayForm form)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(form.OrderId);
            var user = await UserManager.FindByIdAsync(order.UserId);

            if (string.IsNullOrEmpty(order.ReceiverAddress) && order.ShoppingCartType == ShoppingCarts.ShoppingCartType.ShoppingItems)
            {
                throw new UserFriendlyException("请填写收货地址");
            }
            await CurrentUnitOfWork.SaveChangesAsync();
            var amount = Math.Round(order.ActualAmount, 2).ToString();
            var payParams = string.Empty;
            try
            {
                if (order.ActualAmount > 0)
                {
                    order.PayType = form.PayType.Value;
                    //微信公众号付款
                    if (form.PayType == null || form.PayType.Equals(PayType.WechatPay))
                    {
                        payParams = PayContext.PayParams(order.OrderNo, "购买商品", $"金额{amount}元", amount, PayType.WechatPay, user.OpenId);
                    }
                    //微信app付款
                    else if (form.PayType.Equals(PayType.WechatAppPay))
                    {
                        payParams = PayContext.PayParams(order.OrderNo, "购买商品", $"金额{amount}元", amount, PayType.WechatAppPay);
                    }
                    //支付宝app付款
                    else if (form.PayType.Equals(PayType.AliPay))
                    {
                        payParams = PayContext.PayParams(order.OrderNo, "购买商品", $"金额{amount}元", amount, PayType.AliPay);
                    }
                    //钱包付款
                    else if (form.PayType.Equals(PayType.WalletPay))
                    {
                        payParams = OrderManager.PayByWallet(order.OrderNo, Decimal.Parse(amount), PayType.WalletPay);
                    }
                    //体验金付款
                    else if (form.PayType.Equals(PayType.PointPay))
                    {
                        payParams = OrderManager.PayByPoint(order.OrderNo, Decimal.Parse(amount), PayType.PointPay);
                    }
                    //可用体验金付款
                    else if (form.PayType.Equals(PayType.CanUsedPointPay))
                    {
                        payParams = OrderManager.PayByCanUsePoint(order.OrderNo, Decimal.Parse(amount), PayType.CanUsedPointPay);
                    }
                }
            }
            catch
            (Exception e)
            {
                OrderManager.Writelog(e.Message);
            }
            return order.ToVO<Order, OrderVO>((o, vo) =>
            {
                vo.PayParams = payParams;
                vo.OrderDetails = o.OrderDetails.Where(x => x.IsRefund == false).ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                {
                    var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                    dvo.inItem = itemSpec.Item;
                    dvo.inItemSpec = itemSpec;
                });
            });
        }

        public async Task<ListResultDto<UserAddressVO>> RemoveUserAddressAsync(SingleId<long> form)
        {
            await _userAddressRepository.DeleteAsync(form.Id);
            await CurrentUnitOfWork.SaveChangesAsync();
            var userId = AbpSession.GetUserId();
            return await _userAddressRepository.GetAll().Where(x => x.UserId == userId)
                .OrderByDescending(x => x.IsDefault)
                .ToListResultDtoAsync<UserAddress, UserAddressVO>();
        }

        public async Task SetDefaultPackPriceAsync(PackPriceForm form)
        {

            var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
            var userId = AbpSession.GetUserId();
            var orders = await _orderRepository.GetAll().FirstOrDefaultAsync(x => x.Id == order.Id);
            var user = await UserManager.FindByIdAsync(order.UserId);
            if (order.IsPackPrice == form.IsPackPrice)
            {
                order.IsPackPrice = true;
                await _orderRepository.UpdateAsync(order);
            }
            else if (order.IsPackPrice == false && order.IsPackPrice != form.IsPackPrice)
            {
                order.IsPackPrice = true;
                await _orderRepository.UpdateAsync(order);
            }
            else if (order.IsPackPrice == true && order.IsPackPrice != form.IsPackPrice)
            {
                order.IsPackPrice = false;
                await _orderRepository.UpdateAsync(order);
            }
            if (order.IsPackPrice == true)
            {
                await OrderManager.ComputerAmountAsync(order);

            }
            else
            {
                await OrderManager.ComputerAmountAsync(order);
            }
        }

        public async Task<ListResultDto<UserAddressVO>> SaveUserAddressAsync(UserAddressForm form)
        {
            var address = await _userAddressRepository.FirstOrDefaultAsync(form.Id);
            var userId = AbpSession.GetUserId();
            if (address != null)
            {
                address = form.MapTo(address);
                await _userAddressRepository.UpdateAsync(address);
            }
            else
            {
                address = form.MapTo<UserAddress>();
                address.UserId = userId;
                await _userAddressRepository.InsertAsync(address);
            }
            CurrentUnitOfWork.SaveChanges();
            var addresses = _userAddressRepository.GetAll().Where(x => x.UserId == userId)
                .OrderByDescending(x => x.IsDefault);
            return await addresses.ToListResultDtoAsync<UserAddress, UserAddressVO>();
        }


        public async Task<ListResultDto<UserAddressVO>> SetDefaultUserAddressAsync(SingleId<long> form)
        {
            var address = await _userAddressRepository.FirstOrDefaultAsync(form.Id);
            var userId = AbpSession.GetUserId();
            if (address != null)
            {
                address.IsDefault = true;
                var otherAddresses = _userAddressRepository.GetAll()
                    .Where(x => x.UserId == userId && x.Id != address.Id)
                    .ToList();
                otherAddresses.ForEach(x => x.IsDefault = false);
                CurrentUnitOfWork.SaveChanges();
            }
            var addresses = _userAddressRepository.GetAll().Where(x => x.UserId == userId)
                .OrderByDescending(x => x.IsDefault);
            return await addresses.ToListResultDtoAsync<UserAddress, UserAddressVO>();
        }

        public async Task CancelAsync(SingleId<long> form)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
            order.Status = OrderStatus.Cancel;
        }

        public async Task<OrderVO> NewOrderAsync(SingleId<long> form)
        {
            var user = await UserManager.FindByIdAsync(AbpSession.GetUserId());
            var oldOrder = await _orderRepository.FirstOrDefaultAsync(form.Id);
            if (oldOrder.IsGroup)
            {
                throw new UserFriendlyException("请前往拼团");
            }
            var order = new Order
            {
                UserId = oldOrder.UserId,
                OrderNo = Functions.NewOrderNo(),
            };
            var orderId = await _orderRepository.InsertAndGetIdAsync(order);
            var items = await _orderDetailRepository.GetAllListAsync(x => x.OrderId == oldOrder.Id);
            var amount = items.Select(x => (user.IsVip ? (user.VipLevel > 1 ? x.ItemSpec.SuperVipPrice : x.ItemSpec.VipPrice) : x.ItemSpec.Price) * x.Qty).Sum();
            items.ForEach(item =>
            {
                _orderDetailRepository.Insert(new OrderDetail
                {
                    OrderId = orderId,
                    ItemSpecId = item.ItemSpecId,
                    Price = user.IsVip ? (user.VipLevel > 1 ? item.ItemSpec.SuperVipPrice : item.ItemSpec.VipPrice) : item.ItemSpec.Price,
                    Qty = item.Qty,
                    Freight = item.Freight
                });
            });
            await CurrentUnitOfWork.SaveChangesAsync();
            order = await _orderRepository.FirstOrDefaultAsync(orderId);
            order.Amount = amount;
            await OrderManager.ComputerAmountAsync(order);
            order.Status = OrderStatus.WaitPay;
            return order.ToVO<Order, OrderVO>((o, vo) =>
            {
                vo.OrderDetails = o.OrderDetails.Where(x => x.IsRefund == false).ToListVO<OrderDetail, OrderDetailVO>((d, dvo) =>
                 {
                     var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                     dvo.inItem = itemSpec.Item;
                     dvo.inItemSpec = itemSpec;
                 });
            });
        }

        public async Task ConfirmGetAsync(SingleId<long> form)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(form.Id);
            if (order.Status == OrderStatus.Sent)
            {
                order.Status = OrderStatus.Successed;
                order.ReceiveTime = DateTime.Now;
            }
            else
            {
                throw new UserFriendlyException("当前状态不能收货");
            }
        }

        public async Task CommentAsync(OrderCommentForm form)
        {
            var userId = AbpSession.GetUserId();
            var order = await _orderRepository.FirstOrDefaultAsync(form.OrderId);
            if (order == null)
            {
                throw new UserFriendlyException("订单不存在");
            }
            if (order.Status != OrderStatus.Successed)
            {
                throw new UserFriendlyException("当前状态不能评价");
            }
            foreach (var i in form.ItemComments)
            {
                //var item = await _itemRepository.FirstOrDefaultAsync(i.ItemId);
                //if (item == null)
                //{
                //    throw new UserFriendlyException("评论的商品id不存在");
                //}
                //var itemSpec = await _itemSpecRepository.FirstOrDefaultAsync(i.ItemSpecId);
                //if (itemSpec == null)
                //{
                //    throw new UserFriendlyException("评论的商品规格id不存在");
                //}
                if (i.Star >= 4)
                {
                    i.Tags = i.Tags.EndsWith(",") ? $"{i.Tags}好评" : $"{i.Tags},好评";
                }
                else if (i.Star <= 1)
                {
                    i.Tags = i.Tags.EndsWith(",") ? $"{i.Tags}差评" : $"{i.Tags},差评";
                }
                OrderManager.CalculateStoreStar(i.ItemId, i.Star);
                await _itemCommentRepository.InsertAsync(new ItemComment
                {
                    ItemId = i.ItemId,
                    ItemSpecId = i.ItemSpecId,
                    UserId = userId,
                    OrderId = order.Id,
                    Star = i.Star,
                    Tags = i.Tags.Trim(','),
                    Comment = i.Comment,
                    CommentImages = i.Images
                });
            }
            //if(order.WorkerId != null)
            //{
            //   var worker = await  _workerDetailRepository.FirstOrDefaultAsync(order.WorkerId.Value);
            //    worker.WokerStar = form.workerComments.WorkerStar;
            //    worker.Tags = form.workerComments.Tags;
            //}
            order.Status = OrderStatus.Appraised;
        }

        public async Task<OrderVO> SetOrderShippingAsync(OrderShippingForm form)
        {
            var order = await _orderRepository.FirstOrDefaultAsync(form.OrderId);
            var user = await UserManager.FindByIdAsync(AbpSession.GetUserId());
            order.ShippingType = form.ShippingType;
            if (order.ShippingType == ShippingType.Get)
            {
                order.Receiver = null;
                order.ReceiverPhone = null;
                order.ReceiverAddress = null;
                order.PostalCode = null;
            }
            else
            {
                order.Receiver = form.Receiver;
                order.ReceiverPhone = form.ReceiverPhone;
                order.ReceiverAddress = form.ReceiverAddress;
                order.PostalCode = form.PostalCode;
            }
            await OrderManager.ComputerAmountAsync(order);
            return order.ToVO<Order, OrderVO>((o, vo) =>
            {
                vo.OrderDetails = o.OrderDetails.Where(x => x.IsRefund == false).ToListVO<OrderDetail, OrderDetailVO>(
                    (d, dvo) =>
                    {
                        var itemSpec = OrderManager.GetPositiveItemSpec(d.ItemSpecId);
                        dvo.inItem = itemSpec.Item;
                        dvo.inItemSpec = itemSpec;
                    }
                    );
            });
        }

        public async Task<GroupOrderVO> GetGroupOrderAsync(SingleId<long> form)
        {
            var groupOrder = await _groupOrderRepository.FirstOrDefaultAsync(x => x.Id == form.Id);
            if (groupOrder == null)
                return null;
            return groupOrder.ToVO<GroupOrder, GroupOrderVO>((go, govo) =>
            {
                var details = _groupOrderDetailRepository.GetAll()
                .Where(x => x.GroupOrderId == go.Id)
                .Where(x => x.IsValid)
                .OrderBy(x => x.CreationTime)
                .ToList();
                govo.GroupOrderDetails = details.ToListVO<GroupOrderDetail, GroupOrderDetailMiniVO>((d, dvo) =>
                {
                    dvo.inUser = d.Order.User;
                });
                govo.ItemName = go.ItemSpec?.Item?.Name;
                govo.GroupOrderItemSpec = go.ItemSpec.ToVO<ItemSpec, ItemSpecVO>();
            });
        }

        public async Task<GroupOrderVO> GetGroupOrderByOrderIdAsync(SingleId<long> form)
        {
            var groupOrderDetail = await _groupOrderDetailRepository.FirstOrDefaultAsync(x => x.OrderId == form.Id);
            if (groupOrderDetail == null)
                return null;
            var groupOrder = await _groupOrderRepository.FirstOrDefaultAsync(x => x.Id == groupOrderDetail.GroupOrderId);
            if (groupOrder == null)
                return null;
            return groupOrder.ToVO<GroupOrder, GroupOrderVO>((go, govo) =>
            {
                var details = _groupOrderDetailRepository.GetAll()
                .Where(x => x.GroupOrderId == go.Id)
                .Where(x => x.IsValid)
                .OrderBy(x => x.CreationTime)
                .ToList();
                govo.GroupOrderDetails = details.ToListVO<GroupOrderDetail, GroupOrderDetailMiniVO>((d, dvo) =>
                {
                    dvo.inUser = d.Order.User;
                });
                govo.ItemName = go.ItemSpec?.Item?.Name;
                govo.GroupOrderItemSpec = go.ItemSpec.ToVO<ItemSpec, ItemSpecVO>();
            });
        }
        public async Task<PagedResultDto<UserBuyDetailVO>> GetUserBuysAsync(OrderTreePagedForm form)
        {
            var userId = AbpSession.GetUserId();
            var query = _orderRepository.GetAll().Where(x => x.ShoppingCartType == ShoppingCartType.TreeShopping && x.Status == OrderStatus.Paid && x.ItemId==form.ItemId).OrderByDescending(x => x.CreationTime);
            return await query.ToPagedResultDtoAsync<Order, UserBuyDetailVO>(form, (o, vo) =>
            {
                vo.Avatar = o.User.Avatar;
                vo.UserName = o.User.Name;
                if (o.IsFriend)
                {
                    var friend = _userRepository.FirstOrDefault(x => x.Id == o.FriendUserId);
                    vo.FriendAvatar = friend.Avatar;
                    vo.FriendUserName = friend.Name;
                }
                vo.TreeQty = o.OrderDetails.FirstOrDefault().Qty;
                vo.CreationTime = o.PayTime;
            });
        }

        public async Task<PagedResultDto<UserDividendsAmountVO>> GetAllUserDividendAsync(ItemDividedForm form)
        {
            var query = _orderRepository.GetAll().Where(x => x.ShoppingCartType == ShoppingCartType.TreeShopping && x.Status == OrderStatus.Paid && x.DividendEndTime > DateTime.Now && x.ItemId == form.ItemId).OrderByDescending(x => x.CreationTime);
            return await query.ToPagedResultDtoAsync<Order, UserDividendsAmountVO>(form, (o, uo) =>
            {
                uo.Avatar = o.User.Avatar;
                uo.Name = o.User.Name;
                uo.Profit = o.OrderDetails.FirstOrDefault()?.ItemSpec?.Item?.DividendAmount * o.ActualAmount ?? 0;
                uo.DividendEndTime = o.DividendEndTime;
            });
        }
    }
}
